/** <!--------------------------------------------------------------------------------------------->
 * @file RevGraphItem.h
 *
 * GSvn - A Graphical Client for SVN
 * Copyright (C) 2012  Karl Krach, gsvn@bluespirit.la
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 <!---------------------------------------------------------------------------------------------> */


#ifndef REVGRAPHITEM_H
#define REVGRAPHITEM_H

// -- includes --
#include <QGraphicsItem>
#include "RevModelItem.h"
#include <QMap>

// --- forward declarations ---
class RevGraphItemLink;
class RevGraphBranch;

// --- namespaces ---
// --- defines ---


/** <!--------------------------------------------------------------------------------------------->
 * Element of a revision graph
 *
 * @author	Karl Krach, <gsvn@bluespirit.la>
 * @since	2012-02-11
 <!---------------------------------------------------------------------------------------------> */
class RevGraphItem : public QGraphicsItem
{

	/* Con-/Destructors */
public:

	/** <!----------------------------------------------------------------------------------------->
	 * Creates the RevGraphItem object
	 *
	 * @param pCenterRevID (in) revision of the centered item
	 * @param iRevID       (in) revision id of this graph item
	 <!-----------------------------------------------------------------------------------------> */
	RevGraphItem( int* pCenterRevID, int iRevID );

	/** <!----------------------------------------------------------------------------------------->
	 * Creates the RevGraphItem object with the given model item
	 *
	 * @param pCenterRevID (in) revision of the centered item
	 * @param pModelItem   (in) model item to visualize
	 <!-----------------------------------------------------------------------------------------> */
	RevGraphItem( int* pCenterRevID, QSP<RevModelItem> pModelItem );

	/** <!----------------------------------------------------------------------------------------->
	 * Deletes the RevGraphItem object
	 <!-----------------------------------------------------------------------------------------> */
	virtual ~RevGraphItem();


	/* Methods */
public:

	/** <!----------------------------------------------------------------------------------------->
	 * Sets the data of the given model item to be visualized.
	 *
	 * @param pModelItem (in) model item to visualize
	 <!-----------------------------------------------------------------------------------------> */
	void setData( QSP<RevModelItem> pModelItem );

	/** <!----------------------------------------------------------------------------------------->
	 * Sets the branch-link which gives the item access to all other items in this branch (e.g. to
	 * its pre- and successor)
	 *
	 * @param rBranchLink (in) branch link to set
	 <!-----------------------------------------------------------------------------------------> */
	void setBranchLink( const RevGraphItemLink& rBranchLink );

	/** <!----------------------------------------------------------------------------------------->
	 * Sets the global-link which gives the item access to all other items
	 *
	 * @param rLink (in) global link to set
	 <!-----------------------------------------------------------------------------------------> */
	void setGlobalLink( const RevGraphItemLink& rLink );

	/** <!----------------------------------------------------------------------------------------->
	 * Returns the revision ID of this node
	 *
	 * @returns the revision ID
	 <!-----------------------------------------------------------------------------------------> */
	int getRevisionID() const { return m_iRevID; }

	/** <!----------------------------------------------------------------------------------------->
	 * Returns the branch index of this item (or -1 when there is no item set)
	 *
	 * @returns the branch index
	 <!-----------------------------------------------------------------------------------------> */
	BranchIndex getBranchIndex() const
	{
		return ( m_pModelItem.isNull() ? -1 : m_pModelItem->m_iBranchIndex);
	}

	/** <!----------------------------------------------------------------------------------------->
	 * Returns the width of an item including the space to the next item
	 *
	 * @returns the bounding width
	 <!-----------------------------------------------------------------------------------------> */
	static int getStaticBoundingWidth() { return S_FULL_WIDTH + S_SPACE; }

	/** <!----------------------------------------------------------------------------------------->
	 * Creates the tooltip string
	 *
	 * @return the created tooltip string
	 <!-----------------------------------------------------------------------------------------> */
	QString createToolTipString() const;

	/** <!----------------------------------------------------------------------------------------->
	 * Registers the copy info at this graph item
	 *
	 * @param aCopyInfo (in) copy info to register
	 <!-----------------------------------------------------------------------------------------> */
	void registerCopyInfo( const QList<SvnHistoryListener::SvnCopyInfo>& aCopyInfo ) const;

	/** <!----------------------------------------------------------------------------------------->
	 * In difference to Qt's boundingRect() method, getItemBoundingRect() returns the bounding rect
	 * of the item (without arrows, etc)
	 *
	 * @returns bounding rectangular of item
	 <!-----------------------------------------------------------------------------------------> */
	QRectF getItemBoundingRect() const;


	/* Override QGraphicsItem */
public:
	/** <!----------------------------------------------------------------------------------------->
	 * This function defines the outer bounds of the item as a rectangle; all painting must be
	 * restricted to inside an item's bounding rect. QGraphicsView uses this to determine whether
	 * the item requires redrawing.
	 *
	 * Note: For shapes that paint an outline / stroke, it is important to include half the pen
	 * width in the bounding rect. It is not necessary to compensate for antialiasing, though.
	 *
	 * @returns the item's bounding rect
	 <!-----------------------------------------------------------------------------------------> */
	QRectF boundingRect() const;

	/** <!----------------------------------------------------------------------------------------->
	 * This function, which is usually called by QGraphicsView, paints the contents of an item in
	 * local coordinates.
	 *
	 * @param pPainter (in) painter to paint the graphics item
	 * @param pOption  (in) provides the style for the item (such as its state, exposed area, etc)
	 * @param pWidget  (in) points to the widget that is being painted on
	 <!-----------------------------------------------------------------------------------------> */
	void paint( QPainter* pPainter, const QStyleOptionGraphicsItem* pOption, QWidget* pWidget );


	/* Private Methods */
private:

	/** <!----------------------------------------------------------------------------------------->
	 * Paints the 'background' rectangular
	 *
	 * @param pPainter (in) painter to draw rect to
	 * @param rRect    (in) rectangular position
	 <!-----------------------------------------------------------------------------------------> */
	void paintItemRect( QPainter* pPainter, const QRectF& rRect );

	/** <!----------------------------------------------------------------------------------------->
	 * Paints the item text
	 *
	 * @param pPainter (in) painter to draw text to
	 * @param rRect    (in) position to paint the text to
	 <!-----------------------------------------------------------------------------------------> */
	void paintItemText( QPainter* pPainter, const QRectF& rRect );

	/** <!----------------------------------------------------------------------------------------->
	 * Paints the arrow to the previous item (also branching arrows)
	 *
	 * @param pPainter (in) painter to draw arrow to
	 <!-----------------------------------------------------------------------------------------> */
	void paintPrevArrow( QPainter* pPainter );

	/** <!----------------------------------------------------------------------------------------->
	 * Paints an arrow to the given item
	 *
	 * @param pPainter    (in) painter to draw arrow on
	 * @param pTargetItem (in) item to draw the arrow to
	 * @param eColor      (in) color of the arrow
	 * @param bWithArrow  (in) true, of paint an arrow
	 <!-----------------------------------------------------------------------------------------> */
	void paintLineTo( QPainter* pPainter, const RevGraphItem* pTargetItem, Qt::GlobalColor eColor,
	                  bool bWithArrow=false );


	/* Members */
private:

	/** <!----------------------------------------------------------------------------------------->
	 * Revision of this graph item
	 <!-----------------------------------------------------------------------------------------> */
	int m_iRevID;

	/** <!----------------------------------------------------------------------------------------->
	 * Pointer to the ID of the center revision (revision with is at coordinates 0x0)
	 <!-----------------------------------------------------------------------------------------> */
	const int* m_pCenterRevID;

	/** <!----------------------------------------------------------------------------------------->
	 * Model item to visualize
	 <!-----------------------------------------------------------------------------------------> */
	QSP<RevModelItem> m_pModelItem;

	/** <!----------------------------------------------------------------------------------------->
	 * Size of the widget
	 <!-----------------------------------------------------------------------------------------> */
	static const int S_FULL_WIDTH=160, S_FULL_HEIGHT=70;

	/** <!----------------------------------------------------------------------------------------->
	 * Size of the widget
	 <!-----------------------------------------------------------------------------------------> */
	static const int S_SPACE=20;

	/** <!----------------------------------------------------------------------------------------->
	 * Link to the next and previous items (globally - needed to determine y position!)
	 <!-----------------------------------------------------------------------------------------> */
	RevGraphItemLink* m_pGlobalLink;

	/** <!----------------------------------------------------------------------------------------->
	 * Link to the next and previous items (branch-wide - needed to determine x position and draw
	 * arrows between elements!)
	 <!-----------------------------------------------------------------------------------------> */
	RevGraphItemLink* m_pBranchLink;

	/** <!----------------------------------------------------------------------------------------->
	 * List of graph items, which are the source for the branch (where the branch was branched from)
	 <!-----------------------------------------------------------------------------------------> */
	mutable QList<RevGraphItem*> m_aBranchSource;

	/** <!----------------------------------------------------------------------------------------->
	 * "Caching flag" for registering the copy info data
	 <!-----------------------------------------------------------------------------------------> */
	mutable bool m_bCopyInfoRegistered;

};	// END class RevGraphItem

#endif // REVGRAPHITEM_H
